-- card: 4967 from stack: in.3 -- bmap block id: 0 -- flags: 4000 -- background id: 3241 -- name: PictureShow ----- HyperTalk script ----- on Install put ChooseTargetStack() into stackName InstallResource XCMD,PictureShow,stackName InstallResource XCMD,PictureHide,stackName end Install -- part 1 (button) -- low flags: 00 -- high flags: A003 -- rect: left=65 top=300 right=322 bottom=200 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: PictureShow ----- HyperTalk script ----- on mouseUp global butterflies if butterflies is "TRUE" then PictureHide "Butterfly" put FALSE into butterflies set the name of me to "PictureShow" else PictureShow "Butterfly",50,54,0,stay get the result if "Error" is not in it then put TRUE into butterflies set the name of me to "PictureHide" end if end if end mouseUp -- part 5 (field) -- low flags: 81 -- high flags: 2007 -- rect: left=12 top=26 right=298 bottom=491 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 22 -- text size: 10 -- style flags: 0 -- line height: 13 -- part name: Source -- part 7 (button) -- low flags: 00 -- high flags: A003 -- rect: left=299 top=300 right=322 bottom=438 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: Show Pascal Source ----- HyperTalk script ----- on mouseUp set the visible of card field 1 to not the visible of card field 1 if the visible of card field 1 is true then set the name of me to "Hide Pascal Source" else set the name of me to "Show Pascal Source" end mouseUp -- part contents for background part 16 ----- text ----- PICTURESHOW XCMD version 1.0.1 PICTUREHIDE XCMD version 1.0 Kevin Calhoun NOTE TO USERS OF POPUPPICTURE: PictureShow is a revision and extension of PopUpPicture and includes all of PopUpPicture's features. You can use PictureShow in place of PopUpPicture, if you make two changes to your parameters: change the first parameter you passed to PopUpPicture, the ID of a PICT resource, to the name of that PICT resource, and make sure you pass "onPress" as the fifth parameter if you want the picture to disappear the next time the mouse button is pressed and "onRelease" if you want the picture to disappear the next time the mouse button is released. With these changes, PictureShow will work exactly as PopUpPicture did. But if you want to know what the new features are, read on... PictureShow opens a window on top of the current card and displays a picture in it. The type of window in which the picture is displayed can be any of the standard Macintosh window types. The window will automatically be sized to fit the entire picture. You can dispose of the window in two ways: 1) automatically when a mouse event occurs or 2) within a script, as the result of a call to PictureHide. Color pictures (in PICT2 format) will appear in color on a suitably equipped Macintosh and will appear in monochrome on any other machine running System 4.1 or later. PictureShow extracts color table information from pictures in PICT2 format in order to display them in their proper colors. You tell PictureShow what picture to draw by passing it the name of a resource of type PICT, which can be contained in the current stack or in any other open resource file, including the home stack, HyperCard, or the System file. Any picture you've copied to the clipboard can become a resource of type PICT--use the ClipToPICT XFCN to achieve this transformation and to install the new PICT resource in your stack. A file of type PICT can be converted to a PICT resource using the PICTFileToRes XFCN. The name of the PICT resource you pass to PictureShow becomes the title of the window it creates (even when the title is not visible, as in the case of window types that have no title bar). You tell PictureHide what window to dispose of by passing it the same name you passed to PictureShow. If there are two or more windows of the same name created by PictureShow on the screen at the same time, PictureHide will dispose of the one closest to the front. INVOKING PICTURESHOW PictureShow "pictureName",,< top>, , , PictureShow takes six parameters, only the first of which is required. The pictureName is the name of the PICT resource you want displayed. You should enclose this name in quotation marks. The left and top parameters become the horizontal and vertical coordinates of the upper left corner of the picture, given as coordinates in the card window's coordinate system. A left of 0 and a top of 0 would draw the picture flush against the upper left corner of the card window. If either of these parameters is absent, PictureShow centers the picture on the main screen. PictureShow will draw any of the five standard kinds of windows--a windowKind of 0 produces a regular document window with a title bar (but no go-away box), a windowKind of 1 produces a box with a double border, a windowKind of 2 produces a plain box, a windowKind of 3 produces a plain box with shadow, and a windowKind of 16 produces a window with rounded corners and a black title bar. If windowKind is any value other than these, the results depend on which WDEF resources are installed. (If that doesn't make any sense to you, don't worry--nothing bad will happen if you use a far-out value for windowKind.) If the windowKind parameter is absent, PictureShow defaults to a regular document window with a title bar. If you want the picture to remain present until the next time the user pushes the mouse button, pass "onPress" in the fourth parameter, whenToDispose. If you want the picture to remain present until the next time the user releases the mouse button, pass "onRelease" as whenToDispose. If you want the window to remain on the screen until you call PictureHide to get rid of it, pass "stay" as whenToDispose. If you don't provide this parameter, or if you pass something PictureShow doesn't recognize, PictureShow leaves the window on the screen until PictureHide is called to dispose of it. (Note: For compatibility with PopUpPicture, TRUE means the same thing as onRelease.) If you want the event that causes the picture to be removed (a mouseDown if whenToDispose is onMouseUp, a mouseUp if whenToDispose is onMouseUp) to be passed on to HyperCard so that it causes a HyperTalk message to be generated, pass "true" in the passThru parameter. INVOKING PICTUREHIDE PictureHide pictureName The only parameter pictureName takes is the name of the window to be disposed of, which is the same as the name of the PICT that's drawn in the window. (Note: PictureHide disposes only of windows that PictureShow created.) EXAMPLES: PictureShow "Butterfly",40,56,3,onPress PictureShow "Dartmouth Arms",19,34,2,stay PictureHide "Dartmouth Arms" REVISION HISTORY 1.0 -- May 4, 1989. 1.0.1 -- June 17, 1989. Will not display picture unless at least 33K of memory will remain free after the picture is loaded and the window is drawn. (HyperCard quits if it finds less than 32K of memory free on idle.) -- part contents for card part 5 ----- text ----- UNIT PopUpPicture; { PictureShow XCMD © 1988-1989 by the Trustees of Dartmouth College } { Written by Kevin Calhoun } { This source compatible with MPW Pascal 3.0 } (* Pascal PictureShow.p Link -m ENTRYPOINT ∂ -o "YourFile" ∂ -rt XCMD=6464 ∂ -sn Main=PictureShow ∂ PictureShow.p.o ∂ "{Libraries}"interface.o ∂ "{PLibraries}"Paslib.o ∂ "{Libraries}"HyperXLib.o *) {$R-} INTERFACE USES Types, Memory, Windows, Palettes, OSEvents, Desk, Resources, ToolUtils, Packages, HyperXCmd; TYPE Disposal = (onMouseDown, onMouseUp, letItLive); PROCEDURE EntryPoint (paramPtr : XCMDPtr); IMPLEMENTATION PROCEDURE PopItUpAlready (paramPtr : XCMDPtr); FORWARD; PROCEDURE EntryPoint (paramPtr : XCMDPtr); BEGIN PopItUpAlready(paramPtr); END; FUNCTION ColorQDExists : BOOLEAN; { is Color QuickDraw present ? } VAR theWorld: SysEnvRec; err: OSErr; BEGIN err := SysEnvirons(1, theWorld); ColorQDExists := theWorld.hascolorQD; END; FUNCTION GetScreenBitsBounds: Rect; { get screenbits.bounds from the QuickDraw globals } TYPE LongwordPtr = ^LONGINT; BitMapPtr = ^BitMap; CONST screenBitsOffset = -122; CurrentA5 = $904; VAR screenBitsPtr : BitMapPtr; myLongwordPtr : LongwordPtr; BEGIN myLongwordPtr := LongwordPtr(CurrentA5); { myLongwordPtr now points to the pointer to the first QD global } myLongwordPtr := LongwordPtr(myLongwordPtr^); { myLongwordPtr now points to the first QD global } screenBitsPtr := BitMapPtr(myLongwordPtr^ + screenBitsOffset); { screenBitsPtr now points to the screenBits BitMap } GetScreenBitsBounds := screenBitsPtr^.bounds; END; FUNCTION GetLocOfCardWindow (cardWindow : WindowPtr) : Point; VAR savePort : GrafPtr; pt: Point; BEGIN GetPort(savePort); SetPort(cardWindow); SetPt(pt,0,0); LocalToGlobal(pt); SetPort(savePort); GetLocOfCardWindow := pt; END; PROCEDURE CenterRect(VAR r: Rect; inRect: Rect; doH, doV: BOOLEAN); VAR hSize, vSize: INTEGER; hCoord, vCoord: INTEGER; BEGIN WITH r DO BEGIN hCoord := left; vCoord := top; hSize := right-left; vSize := bottom-top; END; WITH inRect DO BEGIN IF doH THEN hCoord := (right-left - hSize) DIV 2 + left; IF doV THEN vCoord := (bottom-top - vSize) DIV 2 + top; END; SetRect(r, hCoord, vCoord, hCoord+hSize, vCoord+vSize); END; PROCEDURE CopyCTab(source: CTabHandle; VAR dest: CTabHandle); VAR err: OSErr; BEGIN dest := NIL; dest := source; err := HandToHand(Handle(dest)); END; PROCEDURE PICT2CTab(srcBits: PixMap; srcRect: Rect; dstRect: Rect; mode: INTEGER; maskRgn: RgnHandle); VAR cTab: CTabHandle; { Copy the last color table we find in a quickdraw picture. We'll use this as a temporary replacement for StdBits. We store any color table we copy in the refcon field of the frontmost window, and we assume that anything we find there is already a handle to a color table. } BEGIN if BitTst(@srcBits.rowBytes,0) THEN { we've got a pixMap } BEGIN IF srcBits.pmTable <> NIL THEN BEGIN cTab := CTabHandle(GetWRefCon(FrontWindow)); IF cTab <> NIL THEN DisposCTable(cTab); CopyCTab(srcBits.pmTable, cTab); SetWRefCon(FrontWindow,LONGINT(cTab)); END; END; END; PROCEDURE GetPaletteFromPICT(picHndl: PicHandle; VAR pltt: PaletteHandle); { Set the QuickDraw bottleneck routine that handles bit copying to our routine that copies the color table of a pixmap. We get the handle to the color table from the refcon field of the frontmost window, which is our window at this point. All of this manipulation of the refcon field of the frontmost window is fairly ugly, but it's an acceptable way to do this without using global variables (if the frontmost window is a color window--in this case we know it is, because we created it). } LABEL 99; CONST kExtremeNeg = -32768; kExtremePos = 32767 - 1; VAR windPtr: WindowPtr; cTab: CTabHandle; entries: INTEGER; saveRefCon: LONGINT; hs: SignedByte; procsStorage: Handle; saveProcsPtr: QDProcsPtr; cProcsPtr: CQDProcsPtr; rct: Rect; theMaxDevice: GDHandle; BEGIN pltt := NIL; windPtr := FrontWindow; saveRefCon := GetWRefCon(windPtr); SetWRefCon(windPtr,0); procsStorage := NewHandle(SIZEOF(CQDProcs)); IF MemError <> noErr THEN GOTO 99; MoveHHi(procsStorage); HLock(procsStorage); cProcsPtr := CQDProcsPtr(procsStorage^); saveProcsPtr := windPtr^.grafProcs; SetStdCProcs(cProcsPtr^); cProcsPtr^.bitsProc := @PICT2CTab; windPtr^.grafProcs := QDProcsPtr(cProcsPtr); hs := HGetState(Handle(picHndl)); HLock(Handle(picHndl)); rct := picHndl^^.picFrame; WITH rct DO SetRect(rct,16384,16384, 16384+(right-left),16384+(bottom-top)); { make sure the drawing is done offscreen } DrawPicture(picHndl, rct); HSetState(Handle(picHndl),hs); windPtr^.grafProcs := saveProcsPtr; DisposHandle(procsStorage); cTab := CTabHandle(GetWRefCon(FrontWindow)); IF cTab = NIL THEN BEGIN { we'll get the default color table for the deepest device } SetRect(rct, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos); theMaxDevice := GetMaxDevice(rct); cTab := GetCTable(theMaxDevice^^.gdPMap^^.pixelSize); DetachResource(Handle(cTab)); END; IF cTab <> NIL THEN BEGIN { now we'll make an "intolerant" palette for our window with these colors } entries := cTab^^.ctSize + 1; pltt := NewPalette(entries,cTab,pmTolerant,$0000); DisposCTable(cTab); END; 99: SetWRefCon(windPtr,saveRefCon); END; PROCEDURE PopItUpAlready (paramPtr : XCMDPtr); LABEL 98,99,100; VAR err: OSErr; reserve: Handle; cardPort : grafPtr; picName: Str255; str: Str255; rTop : INTEGER; rLeft : INTEGER; windKind : INTEGER; picHndl : PicHandle; r : rect; centerH,centerV: BOOLEAN; wStorage : Handle; color: BOOLEAN; windPtr : WindowPtr; pltt: PaletteHandle; anEvent : EventRecord; cardTopLeft : Point; pictureByeBye : Disposal; theMask : INTEGER; passThru : BOOLEAN; PROCEDURE PassReturnValue (theMsg : Str255); { set theResult and quit } BEGIN paramPtr^.returnValue := PasToZero(paramPtr, theMsg); END; BEGIN IF paramPtr^.paramCount = 0 THEN BEGIN PassReturnValue('PictureShow XCMD 1.0.1, 17 June 1989, ©1988-1989 Dartmouth College'); GOTO 100; END; reserve := NewHandle(33000); err := MemError; IF err <> noErr THEN GOTO 100; GetPort(cardPort); ZeroToPas(paramPtr,paramPtr^.params[1]^,picName); picHndl := PicHandle(GetNamedResource('PICT', picName)); IF picHndl = NIL THEN BEGIN err := ResError; GOTO 99; END; DetachResource(Handle(picHndl)); HNoPurge(Handle(picHndl)); r := picHndl^^.picFrame; windKind := 0; pictureByeBye := letItLive; passThru := FALSE; centerH := TRUE; centerV := TRUE; IF paramPtr^.paramCount > 2 THEN BEGIN ZeroToPas(paramPtr, paramPtr^.params[2]^, str); rLeft := StrToNum(paramPtr, str); centerH := (LENGTH(str) = 0); ZeroToPas(paramPtr, paramPtr^.params[3]^, str); rTop := StrToNum(paramPtr, str); centerV := (LENGTH(str) = 0); cardTopLeft := GetLocOfCardWindow(WindowPtr(cardPort)); WITH r, cardTopLeft DO OffsetRect(r,-left+rLeft + h,-top+rTop + v); END ELSE GOTO 98; IF paramPtr^.paramCount > 3 THEN BEGIN ZeroToPas(paramPtr, paramPtr^.params[4]^, str); windKind := StrToNum(paramPtr, str); END ELSE GOTO 98; IF paramPtr^.paramCount > 4 THEN BEGIN ZeroToPas(paramPtr, paramPtr^.params[5]^, str); IF (IUEqualString(str, 'TRUE') = 0) OR (IUEqualString(str, 'onRelease') = 0) THEN pictureByeBye := onMouseUp ELSE IF IUEqualString(str, 'onPress') = 0 THEN pictureByeBye := onMouseDown ELSE IF IUEqualString(str, 'stay') = 0 THEN pictureByeBye := letItLive; END ELSE GOTO 98; IF paramPtr^.paramCount > 5 THEN BEGIN ZeroToPas(paramPtr, paramPtr^.params[6]^, str); passThru := StrToBool(paramPtr, str); END; 98: wStorage := NewHandle(SIZEOF(WindowRecord)); err := MemError; IF err <> noErr THEN BEGIN DisposHandle(Handle(picHndl)); GOTO 98; END; MoveHHi(wStorage); HLock(wStorage); InitCursor; CenterRect(r,GetScreenBitsBounds,centerH,centerV); color := ColorQDExists; IF color THEN windPtr := NewCWindow(wStorage^, r, picName, TRUE, windKind, POINTER(-1), FALSE, 0) ELSE windPtr := NewWindow(wStorage^, r, picName, TRUE, windKind, POINTER(-1), FALSE, 0); IF windPtr = NIL THEN BEGIN DisposHandle(wStorage); DisposHandle(Handle(picHndl)); err := -108; {memFullErr} GOTO 98; END; SetPort(windPtr); ClipRect(windPtr^.PortRect); {make sure clip region is not empty. See Mac Tech Note #59.} {draw the pic into that window} pltt := NIL; IF color THEN BEGIN GetPaletteFromPICT(picHndl, pltt); IF pltt <> NIL THEN BEGIN SetPalette(windPtr, pltt, TRUE); ActivatePalette(windPtr); END; END; MoveHHi(Handle(picHndl)); HLock(handle(picHndl)); DrawPicture(picHndl, windPtr^.PortRect); {draw picture, filling the window} SetOrigin(picHndl^^.picFrame.left,picHndl^^.picFrame.top); SetWindowPic(windPtr, picHndl); HUnlock(Handle(picHndl)); If pictureByeBye = letItLive THEN BEGIN SetWRefCon(windPtr, 51459); { we'll stick this here so we can identify this window as ours } WindowPeek(windPtr)^.windowKind := 514; { and we'll put this here just for extra safety } END ELSE BEGIN { wait for mouse-down or mouse-up } IF pictureByeBye = onMouseUp THEN theMask := mupmask ELSE theMask := mdownMask; REPEAT SystemTask; UNTIL OSEventAvail(theMask, anEvent); IF NOT passThru THEN IF GetNextEvent(theMask, anEvent) THEN ; {get rid of window and pict; restore port, and exit} CloseWindow(windPtr); IF pltt <> NIL THEN DisposePalette(pltt); DisposHandle(wStorage); SetPort(cardPort); SendCardMessage(paramPtr, 'go to this card'); END; 99: DisposHandle(reserve); 100: IF err <> noErr THEN BEGIN NumToString(err,str); PassReturnValue(CONCAT('Error ',str)); END; END; END.